package video

import (
	"common/mildware"
	"common/models"
	"common/validate"
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"strconv"
	"strings"
	"time"
	"video/pkg/dao/redis"
	"video/pkg/dtime"
)

// VideAddLike 点赞-不喜欢-收藏
// @Summary 点赞-不喜欢-收藏
// @Description 点赞-不喜欢-收藏
// @Tags 视频
// @Accept application/json
// @Produce application/json
// @Param Authorization header string true "Bearer 用户令牌"
// @Param object body docModel.DocVideoLikeOrNoReq false "搜索参数"
// @Security ApiKeyAuth
// @Success 200 {object} docModel.DocResp
// @Router /video/update/like [post]
func (h VHandler) videoLikeOrNo(c *gin.Context) {
	var (
		videoInfo *models.VideoInfo
	)
	resp := new(models.RespData)
	req := new(models.VideoLikeOrNoReq)
	if err := c.ShouldBindJSON(req); err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			zap.L().Error("Video:videoLikeOrNo with invalid fail", zap.Error(err))
			resp.SendServerBusy(c)
			return
		} else {
			zap.L().Error("Video:videoLikeOrNo with invalid fail", zap.Error(errs))
			resp.SendCodeWithMsg(c, models.CodeInvalidParam, validate.RemoveTopStruct(errs.Translate(validate.Trans)))
			return
		}
	}
	go func() {
		//获得视频Id
		videoID, err := h.R.GetString(redis.VideIdToID + req.VideoID)
		if err != nil {
			if errors.Is(err, redis.NoKey) {
				videoInfo, err = h.M.VideoInfoQueryByUid(req.VideoID)
				if err != nil {
					zap.L().Error("Video:videoLikeOrNo h.M.VideoInfoQueryByUid err", zap.Error(err))
					resp.SendServerBusy(c)
					return
				}
			}
		}
		if videoID != "" {
			videoInfo, err = h.M.VideoInfoQueryById(videoID)
			if err != nil {
				zap.L().Error("Video:videoLikeOrNo h.M.VideoInfoQueryById err", zap.Error(err))
				resp.SendServerBusy(c)
				return
			}
		}
		//获得用户的token
		ID, _, _, err := mildware.GetCyrrentUserID(c)
		if err != nil {
			zap.L().Error("Video:videoLikeOrNo mildware.GetCyrrentUserID err", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		userInfo, err := h.M.QueryUserInfoByID(ID)
		if err != nil {
			zap.L().Error("Video:videoLikeOrNo  h.M.QueryUserInfoByID err", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		//判断操作事件 - 修改用户的信息  喜欢 | 不喜欢 | 收藏
		videIDStr := strconv.Itoa(int(videoInfo.ID))
		userInfo.LikeVideos = changeUserStatus(req.UserStatusLike, req.UserLikeOp, userInfo.LikeVideos, videIDStr)
		userInfo.DisLikeVideos = changeUserStatus(req.UserStatusDisLike, req.UserDisLikeOp, userInfo.DisLikeVideos, videIDStr)
		userInfo.CollectionVideos = changeUserStatus(req.UserStatusCollect, req.UserCollectOp, userInfo.CollectionVideos, videIDStr)
		//更新用户信息
		if err = h.M.SaveUserInfo(userInfo); err != nil {
			zap.L().Error("Video:videoLikeOrNo  h.M.SaveUserInfo err", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		//修改视频的redis - 并添加到视频定时任务
		str := req.LikeNum + models.SplitFormat + req.DisLikeNum + models.SplitFormat + req.CollectionCount
		if err = h.R.SetString(redis.VideoInfoLikeOrNo+req.VideoID, str, 10*time.Minute); err != nil {
			zap.L().Error("Video:videoLikeOrNo  h.R.SetString err")
			resp.SendServerBusy(c)
			return
		}
		//添加定时修改任务
		dtime.VideoTask.AppendData(req.VideoID, videIDStr)
	}()
	resp.SendSuccess(c)
}
func changeUserStatus(oldStatus, newStatus bool, src, add string) (result string) {
	//如果 原来是 false/tr - 现在是 false -- 不修改
	if oldStatus == false && newStatus == false {
		result = src
		return
	}
	//如果原来是 false 现在是 true - 修改(添加)
	if oldStatus == false && newStatus == true {
		result = operatorListAdd(src, add)
		return
	}
	//如果原来是 true 现在是 false - 不修改
	if oldStatus == true && newStatus == false {
		result = src
		return
	}
	//如果原来是 true 现在是 true - 修改(删除)
	if oldStatus == true && newStatus == true {
		result = operatorListDelete(src, add)
		return
	}
	return
}
func operatorListAdd(src, add string) string {
	//是否是第一次添加
	if src == "" {
		//直接添加
		return add
	}
	list := strings.Split(src, models.SplitFormat)
	list = append(list, add)
	return strings.Join(list, models.SplitFormat)
}
func operatorListDelete(src, add string) string {
	var resultList []string
	if src == "" {
		return src
	}
	videoMap := make(map[string]struct{})
	List := strings.Split(src, models.SplitFormat)
	for _, v := range List {
		videoMap[v] = struct{}{}
	}
	if _, ok := videoMap[add]; !ok {
		return src
	}
	delete(videoMap, add)
	for key, _ := range videoMap {
		resultList = append(resultList, key)
	}
	if len(resultList) == 1 {
		return resultList[0]
	} else if len(resultList) == 0 {
		return ""
	}
	return strings.Join(resultList, models.SplitFormat)
}
